<?php

declare(strict_types=1);
/**
 * This file is part of MoChat.
 * @link     https://mo.chat
 * @document https://mochat.wiki
 * @contact  group@mo.chat
 * @license  https://github.com/mochat-cloud/mochat/blob/master/LICENSE
 */
namespace MoChat\App\WorkContact\Job;

use Hyperf\AsyncQueue\Job;
use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\Logger\LoggerFactory;
use MoChat\App\Corp\Utils\WeWorkFactory;
use MoChat\App\WorkContact\Constants\Employee\Status;
use MoChat\App\WorkContact\Contract\WorkContactContract;
use MoChat\App\WorkContact\Contract\WorkContactEmployeeContract;
use MoChat\App\WorkContact\Queue\SyncContactQueue;
use MoChat\App\WorkEmployee\Contract\WorkEmployeeContract;
use Psr\Log\LoggerInterface;

/**
 * 根据员工id同步客户异步队列Job.
 */
class SyncContactListJob extends Job
{
    /**
     * @var array
     */
    public $params;

    /**
     * @var LoggerInterface
     */
    private $logger;

    public function __construct(array $params)
    {
        $this->params = $params;
    }

    public function handle()
    {
        $corpId = (int) $this->params['corpId'];
        $employeeId = (int) $this->params['employeeId'];
        $wxUserId = (string) $this->params['wxUserId'];
        $loggerFactory = make(LoggerFactory::class);
        $this->logger = $loggerFactory->get(__CLASS__);
        $this->logger->debug(sprintf('同步客户列表队列开始, 企业ID:%s, 员工ID:%s ', (string) $corpId, (string) $employeeId));

        $wxContactUserIds = $this->getWxContactUserIds($corpId, $employeeId, $wxUserId);
        if (empty($wxContactUserIds)) {
            return;
        }

        // 删除员工不存在的客户
        $this->deleteContacts($corpId, $employeeId, $wxContactUserIds);

        $syncContactQueue = make(SyncContactQueue::class);
        foreach ($wxContactUserIds as $key => $wxContactUserId) {
            $this->logger->debug(sprintf('生产同步客户详情队列, 企业ID:%s, 员工ID:%s，客户ID:%s ', (string) $corpId, (string) $employeeId, $wxContactUserId));
            $syncContactQueue->syncContactDetail([
                'corpId' => $corpId,
                'employeeId' => $employeeId,
                'wxExternalUserId' => $wxContactUserId,
            ]);
        }
    }

    /**
     * 从微信拉取客户列表.
     *
     * @param int $corpId 数据表用户ID
     * @param int $employeeId 微信用户ID
     * @return array 相应数组
     */
    private function getWxContactUserIds(int $corpId, int $employeeId, string $wxUserId): array
    {
        $weWorkContactApp = make(WeWorkFactory::class)->getContactApp($corpId);
        $employeeService = make(WorkEmployeeContract::class);
        $employee = $employeeService->getWorkEmployeeById($employeeId, ['wx_user_id']);

        if (empty($employee)) {
            return [];
        }

        $contact = $weWorkContactApp->external_contact->list($wxUserId);

        if ($contact['errcode'] == 0) {
            return $contact['external_userid'];
        }

        if ($contact['errcode'] == 84061) { // 无跟进客户
            $workContactEmployeeService = make(WorkContactEmployeeContract::class);
            $workContactEmployeeService->updateWorkContactEmployeesByEmployeeId($employeeId, ['status' => Status::REMOVE, 'deleted_at' => date('Y-m-d H:i:s')]);
            return [];
        }

        $logger = make(StdoutLoggerInterface::class);
        $logger->error(sprintf('同步客户-获取通讯录用户跟进的客户列表信息失败，error: %s [%s]', json_encode($contact), date('Y-m-d H:i:s')));
        return [];
    }

    /**
     * 删除员工客户信息.
     *
     * @param int $employeeId 员工ID
     * @param array $contactIds 客户ID
     */
    private function deleteContacts(int $corpId, int $employeeId, array $wxContactUserIds)
    {
        // 从数据表中当前员工所有的客户
        $oldContactList = $this->getOldContacts($corpId, $employeeId);
        if (empty($oldContactList)) {
            return;
        }

        $oldContactIds = array_column($oldContactList, 'wxExternalUserid');

        $deleteContactIds = array_diff($oldContactIds, $wxContactUserIds);

        if (empty($deleteContactIds)) {
            return;
        }

        $workContactEmployeeService = make(WorkContactEmployeeContract::class);
        $logger = make(StdoutLoggerInterface::class);
        $res = $workContactEmployeeService->updateWorkContactEmployeesByOtherId($employeeId, $deleteContactIds, ['status' => Status::REMOVE, 'deleted_at' => date('Y-m-d H:i:s')]);
        if (! is_int($res)) {
            $logger->error(sprintf('同步客户-删除员工客户失败，error: %s [%s]', json_encode($res), date('Y-m-d H:i:s')));
        }
    }

    /**
     * 获取旧客户wxid.
     *
     * @param int $employeeId 员工ID
     * @param int $corpId 企业授信ID
     *
     * @return array 相应数组
     */
    private function getOldContacts(int $corpId, int $employeeId): array
    {
        // 员工-客户关联表信息
        $workContactEmployeeService = make(WorkContactEmployeeContract::class);
        $contactEmployeeList = $workContactEmployeeService->getWorkContactEmployeeByCorpIdEmployeeId($employeeId, $corpId, ['id', 'contact_id']);
        if (empty($contactEmployeeList)) {
            return [];
        }

        // 员工表信息
        $workContactService = make(WorkContactContract::class);
        $contactList = $workContactService->getWorkContactsById(array_column($contactEmployeeList, 'contactId'), ['id', 'wx_external_userid']);
        return $contactList ?? [];
    }
}
